<template>
	<view class="e-text" :class="[]" v-if="show" :style="{
            margin: props.margin,
			justifyContent: props.align === 'left' ? 'flex-start' : props.align === 'center' ? 'center' : 'flex-end'
        }" @tap="clickHandler">
		<text :class="['e-text__price', type && `e-text__value--${props.type}`]" v-if="props.mode === 'price'"
			:style="[valueStyle]">￥</text>
		<view class="e-text__prefix-icon" v-if="props.prefixIcon">
			<e-icon :name="props.prefixIcon" :customStyle="addStyle(props.iconStyle)"></e-icon>
		</view>
		<e-link v-if="props.mode === 'link'" :text="textValue" :href="props.href" underLine></e-link>
		<!-- #ifdef MP -->
		<template v-else-if="props.openType">
			<button class="e-reset-button e-text__value" :style="[valueStyle]" :data-index="index"
				:openType="props.openType" @getuserinfo="getuserinfo" @contact="error" @getphonenumber="getphonenumber"
				@error="contact" @launchapp="launchapp" @opensetting="opensetting" :lang="props.lang"
				:session-from="props.sessionFrom" :send-message-title="props.sendMessageTitle"
				:send-message-path="props.sendMessagePath" :send-message-img="props.sendMessageImg"
				:show-message-card="props.showMessageCard" :app-parameter="props.appParameter">
				{{ textValue }}
			</button>
		</template>
		<!-- #endif -->
		<text v-else class="e-text__value" :style="[valueStyle]" :class="[
                props.type && `e-text__value--${props.type}`,
                props.lines && `e-line-${props.lines}`
            ]">{{ textValue }}</text>
		<view class="e-text__suffix-icon" v-if="props.suffixIcon">
			<e-icon :name="props.suffixIcon" :customStyle="addStyle(props.iconStyle)"></e-icon>
		</view>
	</view>
</template>

<script lang="ts">
	import {defineComponent} from 'vue'
	import mpMixin from '../../libs/mixin/mpMixin'
	/**
	 * Text 文本
	 * @description 此组件集成了文本类在项目中的常用功能，包括状态，拨打电话，格式化日期，*替换，超链接...等功能。 您大可不必在使用特殊文本时自己定义，text组件几乎涵盖您能使用的大部分场景。
	 * @tutorial https://www.uviewui.com/components/loading.html
	 * @property {String} 					type					主题颜色
	 * @property {Boolean} 					show					是否显示（默认 true ）
	 * @property {String | Number}			text					显示的值
	 * @property {String}					prefixIcon				前置图标
	 * @property {String} 					suffixIcon				后置图标
	 * @property {String} 					mode					文本处理的匹配模式 text-普通文本，price-价格，phone-手机号，name-姓名，date-日期，link-超链接
	 * @property {String} 					href					mode=link下，配置的链接
	 * @property {String | Function} 		format					格式化规则
	 * @property {Boolean} 					call					mode=phone时，点击文本是否拨打电话（默认 false ）
	 * @property {String} 					openType				小程序的打开方式
	 * @property {Boolean} 					bold					是否粗体，默认normal（默认 false ）
	 * @property {Boolean} 					block					是否块状（默认 false ）
	 * @property {String | Number} 			lines					文本显示的行数，如果设置，超出此行数，将会显示省略号
	 * @property {String} 					color					文本颜色（默认 '#303133' ）
	 * @property {String | Number} 			size					字体大小（默认 15 ）
	 * @property {Object | String} 			iconStyle				图标的样式 （默认 {fontSize: '15px'} ）
	 * @property {String} 					decoration				文字装饰，下划线，中划线等，可选值 none|underline|line-through（默认 'none' ）
	 * @property {String | Number}	margin					外边距，对象、字符串，数值形式均可（默认 0 ）
	 * @property {String | Number} 			lineHeight				文本行高
	 * @property {String} 					align					文本对齐方式，可选值left|center|right（默认 'left' ）
	 * @property {String} 					wordWrap				文字换行，可选值break-word|normal|anywhere（默认 'normal' ）
	 * @property {String}					openType				开放能力，具体请看uniapp稳定关于button组件部分说明
	 * @property {String}					formType				用于 <form> 组件，点击分别会触发 <form> 组件的 submit/reset 事件
	 * @property {String}					lang					指定返回用户信息的语言，zh_CN 简体中文，zh_TW 繁体中文，en 英文（默认 en ）
	 * @property {String}					sessionFrom				会话来源，openType="contact"时有效
	 * @property {String}					sendMessageTitle		会话内消息卡片标题，openType="contact"时有效
	 * @property {String}					sendMessagePath			会话内消息卡片点击跳转小程序路径，openType="contact"时有效
	 * @property {String}					sendMessageImg			会话内消息卡片图片，openType="contact"时有效
	 * @property {Boolean}					showMessageCard			是否显示会话内消息卡片，设置此参数为 true，用户进入客服会话会在右下角显示"可能要发送的小程序"提示，用户点击后可以快速发送小程序消息，openType="contact"时有效（默认false）
	 * @event {Function} click  点击触发事件
	 * @example <e-text text="我用十年青春,赴你最后之约"></e-text>
	 */
	export default defineComponent({
		name: "e-text",
		mixins: [mpMixin]
	});
</script>

<script lang="ts" setup>
	import {
		computed,
		toRefs
	} from 'vue'
	import {
		useOpenType,
		openTypeEmits
	} from '../../libs/hooks'
	import {
		textProps,
		textEmits
	} from './props';
	import {
		addUnit,
		addStyle,
		throwError
	} from '../../libs/utils/_utils'
	import {
		useDefaultProps
	} from '../../libs/hooks'
	import {
		deepMerge,
		isFunction,
		isString,
		isDate,
		isURL,
		timeFormat,
		priceFormat,
		shield
	} from '../../libs/utils'
	import type {
		StyleProperties
	} from "../../libs/tokens";
	import componentsProps, {
		type DefaultProps
	} from "../../libs/config/componentsProps";

	const {
		text: textDefaultProps
	} = toRefs(componentsProps);

	const _props = defineProps(textProps)

	const props = useDefaultProps < DefaultProps['text'] > (_props, textDefaultProps);
	const emit = defineEmits({
		...textEmits,
		...openTypeEmits
	})

	// #ifdef MP
	const {
		getphonenumber,
		getuserinfo,
		error,
		opensetting,
		launchapp,
		contact
	} = useOpenType(emit)
	// #endif

	const textValue = computed(() => {
		const {
			text,
			mode,
			format,
			href
		} = props.value
		if (isFunction(format) && mode !== 'link') {
			// 如果用户传入的是函数，使用函数格式化
			return format(text as string)
		} else {
			// 价格类型
			if (mode === 'price') {
				// 如果text不为金额进行提示
				if (!/^\d+(\.\d+)?$/.test(`${text}`)) {
					throwError('金额模式下，text参数需要为金额格式', 'e-text');
				}
				// 如果format非正则，非函数，则使用默认的金额格式化方法进行操作
				return priceFormat(text || "", 2)
			}
			if (mode === 'date') {
				// 判断是否合法的日期或者时间戳
				!isDate(text) && throwError('日期模式下，text参数需要为日期或时间戳格式', 'e-text')
				// 如果没有设置format，则设置为默认的时间格式化形式
				return timeFormat(text || "", format as string || 'yyyy-mm-dd')
			}
			if (mode === 'phone') {
				if (format === 'encrypt') {
					// 如果format为encrypt，则将手机号进行星号加密处理
					return shield({
						str: `${text}`,
						type: 2,
						shieldCode: '****'
					})
				}
				return text
			}
			if (mode === 'name') {
				// 判断是否合法的字符粗
				if (isString(text)) {
					if (format === 'encrypt') {
						// 如果format为encrypt，则将姓名进行星号加密处理
						return formatName(text)
					}
				} else {
					throwError('姓名模式下，text参数需要为字符串格式', 'e-text')
				}
				return text
			}
			if (mode === 'link') {
				// 判断是否合法的字符粗
				!isURL(href as string) && throwError('超链接模式下，href参数需要为URL格式', 'e-text')
				return text
			}
		}

		return text
	})

	// 默认的姓名脱敏规则
	const formatName = (name: string) => {
		let value = ''
		if (name.length === 2) {
			value = name.substr(0, 1) + '*'
		} else if (name.length > 2) {
			let char = ''
			for (let i = 0, len = name.length - 2; i < len; i++) {
				char += '*'
			}
			value = name.substr(0, 1) + char + name.substr(-1, 1)
		} else {
			value = name
		}
		return value
	}

	const valueStyle = computed(() => {

		const style: StyleProperties = {
			textDecoration: props.value.decoration,
			fontWeight: props.value.bold ? 'bold' : 'normal',
			wordWrap: props.value.wordWrap,
			fontSize: addUnit(props.value.size)
		};
		!props.value.type && (style.color = props.value.color);
		props.value.lineHeight && (style.lineHeight = addUnit(props.value.lineHeight));
		// #ifdef APP-NVUE
		props.value.lines && (style.lines = props.value.lines);
		props.value.block && (style.display = 'block');
		// #endif


		return deepMerge(style, addStyle(props.value.customStyle as Record<string,any>) as Record<string,any>)

	})


	const clickHandler = () => {
		// 如果为手机号模式，拨打电话
		if (props.value.call && props.value.mode === 'phone') {
			uni.makePhoneCall({
				phoneNumber: `${props.value.text}`
			})
		}
		emit('click')
	}
</script>

<style lang="scss" scoped>
	@import "../../libs/theme/text.scss";
</style>
